package com.example.common.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.common.xss.*;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: xss-demo
 * @description: Xss过滤器
 * @author: ChenZhiXiang
 * @create: 2019-07-22 11:36
 **/
public class XssFilter implements Filter {

    private String sensitiveFilePath;

    private SensitiveWord sensitiveWord;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        sensitiveFilePath = filterConfig.getInitParameter("sensitiveFilePath");
        sensitiveWord = new SensitiveWord(sensitiveFilePath);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // 获取请求的URI
        String URI = request.getRequestURI();
        // 若为接口，则过滤参数
        if (!URI.contains(".")){
            // 判断是否为带有文件参数的接口
            if (URI.endsWith("fileApi")){
                //  定义文件上传解析器
                CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
                // 将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中
                MultipartHttpServletRequest multiReq = multipartResolver.resolveMultipart(request);
                Map<String, String> contentTypes = new HashMap<>();
                XssMultipartHttpServletRequestWrapper xssM = new XssMultipartHttpServletRequestWrapper(request, multiReq.getMultiFileMap(), multiReq.getParameterMap(), contentTypes, sensitiveWord);
                filterChain.doFilter(xssM, servletResponse);
                return;
            }
            // 单独处理json参数的接口,xxs漏洞预防
            if (URI.endsWith("jsonApi")) {
                XssJsonHttpServletRequestWrapper xssRequest = new XssJsonHttpServletRequestWrapper((HttpServletRequest) request);
                // 读取请求内容
                BufferedReader br;
                br = xssRequest.getReader();
                String line = null;
                StringBuilder sb = new StringBuilder();
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                // 将json字符串转换为json对象
                JSONObject jsonObject = JSONObject.parseObject(sb.toString());
                for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                    //判断是否包含敏感字符
                    if (sensitiveWord.getSensitiveWord(entry.getValue() == null ? "" : entry.getValue().toString(), 1).size() > 0) {
                        throw new RuntimeException("含有敏感字符");
                    }
                    // 替换危险字符
                    jsonObject.put(entry.getKey(), SequenceTool.xssEncode(entry.getValue()));
                }
                // 把参数转换之后放到我们的body里面
                String json = JSON.toJSONString(jsonObject);
                xssRequest.setBody(json.getBytes("UTF-8"));
                // 放行
                filterChain.doFilter(xssRequest, servletResponse);
                return;
            }
            filterChain.doFilter(new XssHttpServletRequestWrapper(request, sensitiveWord), servletResponse);
            return;
        }
    }

    @Override
    public void destroy() {

    }
}
